package cn.com.blueInfo.utils.util;

import org.springframework.util.Base64Utils;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * JDK8 加密工具类
 * 包含AES对称加密和RSA非对称加密实现
 */
@Deprecated
public class EncryptionUtils {

    // ------------------------ Base64加密 -----------------------------
    private static final Base64.Decoder decoder = Base64.getDecoder();
    private static final Base64.Encoder encoder = Base64.getEncoder();

    /**
     * Base64加密
     * @Title: base64Encode
     * @param expressStr
     * @return String
     * @throws
     */
    public static String Base64Encode(String expressStr) {
        String cipherStr = "";
        byte[] byteStr = expressStr.getBytes(StandardCharsets.UTF_8);
        cipherStr = encoder.encodeToString(byteStr);
        return cipherStr;
    }

    /**
     * Base64解密
     * @Title: base64Decode
     * @param cipherStr
     * @return String
     * @throws
     */
    public static String Base64Decode(String cipherStr) {
        String expressStr = "";
        expressStr = new String(decoder.decode(cipherStr), StandardCharsets.UTF_8);
        return expressStr;
    }

    // ------------------------ MD5加密 --------------------------------

    /**
     * MD5加Base64认证码
     * @Title: md5And64ToStr
     * @param expressStr
     * @return String
     * @throws
     */
    public static String MD5And64ToStr(String expressStr) {
        if (expressStr == null || "".equals(expressStr.trim())) {
            return "";
        }
        return encoder.encodeToString(md5Encode(expressStr));
    }

    /**
     * MD5加密
     * @Title: md5Encode
     * @param expressStr
     * @return byte[]
     * @throws
     */
    private static byte[] md5Encode(String expressStr) {
        byte[] output = null;
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            byte[] input = expressStr.getBytes();
            output = md5.digest(input);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        return output;
    }

    // ------------------------ 对称加密 (DES) --------------------------

    /**
     * @description: 加密方法
     * @author: suxch
     * @date: 2024/8/13 20:54
     * @param encodeStr 需要加密的明文
     * @param privateKey 私钥
     * @return: java.lang.String
     **/
    public String base64Encode(String encodeStr, String privateKey) {
        try {
            byte[] byteArr = this.desEncrypt(encodeStr.getBytes(), privateKey);
            return Base64Utils.encodeToString(byteArr);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @description: 解密方法
     * @author: suxch
     * @date: 2024/8/13 20:56
     * @param decodeStr 需要解密的密文
     * @param privateKey 私钥
     * @return: java.lang.String
     **/
    public String base64Decode(String decodeStr, String privateKey) {
        try {
            byte[] byteArr = Base64Utils.decode(decodeStr.getBytes());
            return new String(this.desDecrypt(byteArr, privateKey), StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * des 加密
     * @param plainText 明文
     * @param desKeyParameter 加密秘钥
     * @return 二进制字节数组
     */
    private byte[] desEncrypt(byte[] plainText, String desKeyParameter) throws Exception {
        return this.desCrypt(plainText, desKeyParameter, Cipher.ENCRYPT_MODE);
    }

    /**
     * des 解密
     * @param encryptText 密文
     * @param desKeyParameter 解密秘钥
     * @return 二进制字节数组
     */
    private byte[] desDecrypt(byte[] encryptText, String desKeyParameter) throws Exception {
        return this.desCrypt(encryptText, desKeyParameter, Cipher.DECRYPT_MODE);
    }

    /**
     * 加密解密核心逻辑
     * @param text 文本
     * @param desKeyParameter 密钥
     * @param cipherType 加密/解密类型
     * @return 二进制字节数组
     */
    private byte[] desCrypt(byte[] text, String desKeyParameter, int cipherType) throws Exception {
        SecureRandom sr = new SecureRandom();
        byte[] rawKeyData = desKeyParameter.getBytes();
        DESKeySpec dks = new DESKeySpec(rawKeyData);
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey key = keyFactory.generateSecret(dks);
        Cipher cipher = Cipher.getInstance("DES");
        cipher.init(cipherType, key, sr);
        return cipher.doFinal(text);
    }

    // ------------------------ 对称加密 (AES) ------------------------

    /**
     * 生成AES密钥
     * @return Base64编码的密钥
     * @throws NoSuchAlgorithmException 算法不存在异常
     */
    public static String generateAesKey() throws NoSuchAlgorithmException {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(128); // 128位密钥
        SecretKey secretKey = keyGenerator.generateKey();
        return Base64.getEncoder().encodeToString(secretKey.getEncoded());
    }

    /**
     * AES加密
     * @param content 待加密内容
     * @param key Base64编码的密钥
     * @return 加密后的Base64字符串
     * @throws Exception 加密异常
     */
    public static String aesEncrypt(String content, String key) throws Exception {
        SecretKeySpec secretKeySpec = new SecretKeySpec(
                Base64.getDecoder().decode(key), "AES");

        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);

        byte[] encrypted = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    /**
     * AES解密
     * @param encryptedContent 加密后的Base64字符串
     * @param key Base64编码的密钥
     * @return 解密后的内容
     * @throws Exception 解密异常
     */
    public static String aesDecrypt(String encryptedContent, String key) throws Exception {
        SecretKeySpec secretKeySpec = new SecretKeySpec(
                Base64.getDecoder().decode(key), "AES");

        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);

        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedContent));
        return new String(decrypted, StandardCharsets.UTF_8);
    }

    // ------------------------ 非对称加密 (RSA) ------------------------

    /**
     * 生成RSA密钥对
     * @return 包含公钥和私钥的字符串数组，[0]为公钥，[1]为私钥
     * @throws NoSuchAlgorithmException 算法不存在异常
     */
    public static String[] generateRsaKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048); // 2048位密钥
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
        String privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());

        return new String[]{publicKey, privateKey};
    }

    /**
     * RSA公钥加密
     * @param content 待加密内容
     * @param publicKey Base64编码的公钥
     * @return 加密后的Base64字符串
     * @throws Exception 加密异常
     */
    public static String rsaEncrypt(String content, String publicKey) throws Exception {
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(
                Base64.getDecoder().decode(publicKey));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey pubKey = keyFactory.generatePublic(keySpec);

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);

        byte[] encrypted = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    /**
     * RSA私钥解密
     * @param encryptedContent 加密后的Base64字符串
     * @param privateKey Base64编码的私钥
     * @return 解密后的内容
     * @throws Exception 解密异常
     */
    public static String rsaDecrypt(String encryptedContent, String privateKey) throws Exception {
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(
                Base64.getDecoder().decode(privateKey));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey priKey = keyFactory.generatePrivate(keySpec);

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, priKey);

        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedContent));
        return new String(decrypted, StandardCharsets.UTF_8);
    }

    // ------------------------ 测试方法 ------------------------
    public static void main(String[] args) {
        try {
            // 测试AES对称加密
            String aesKey = generateAesKey();
            System.out.println("AES密钥: " + aesKey);

            String originalContent = "Hello AES Encryption";
            String aesEncrypted = aesEncrypt(originalContent, aesKey);
            System.out.println("AES加密后: " + aesEncrypted);

            String aesDecrypted = aesDecrypt(aesEncrypted, aesKey);
            System.out.println("AES解密后: " + aesDecrypted);
            System.out.println();

            // 测试RSA非对称加密
            String[] rsaKeys = generateRsaKeyPair();
            System.out.println("RSA公钥: " + rsaKeys[0]);
            System.out.println("RSA私钥: " + rsaKeys[1]);

            String rsaOriginal = "Hello RSA Encryption";
            String rsaEncrypted = rsaEncrypt(rsaOriginal, rsaKeys[0]);
            System.out.println("RSA加密后: " + rsaEncrypted);

            String rsaDecrypted = rsaDecrypt(rsaEncrypted, rsaKeys[1]);
            System.out.println("RSA解密后: " + rsaDecrypted);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
